/**
* 版权声明：厦门睿商网络科技有限公司 版权所有 违者必究
* 日    期：2020-05-27
*/
package com.rzico.order.service;

import com.rzico.account.entity.Payable;
import com.rzico.base.BaseMapper;
import com.rzico.base.impl.BaseServiceImpl;
import com.rzico.basics.entity.Enterprise;
import com.rzico.basics.entity.Product;
import com.rzico.basics.service.EnterpriseService;
import com.rzico.basics.service.ProductService;
import com.rzico.core.entity.SysUser;
import com.rzico.core.service.SysSequenceService;
import com.rzico.core.service.SysUserService;
import com.rzico.exception.CustomException;
import com.rzico.order.entity.*;
import com.rzico.order.enumx.*;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.rzico.order.mapper.WxCheckMapper;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <pre>
 * 盘点单业务类
 * </pre>
 *
 * @author Rzico Boot
 * @version 1.0
 */
@Service
public class WxCheckService extends BaseServiceImpl<WxCheck, String> {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private WxCheckMapper wxCheckMapper;

    @Autowired
    private WxCheckItemService wxCheckItemService;

    @Autowired
    private EnterpriseService enterpriseService;

    @Autowired
    private SysSequenceService sysSequenceService;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private WarehouseStockService warehouseStockService;

    @Autowired
    private ProductService productService;

    @Autowired
    private WarehouseItemService warehouseItemService;

    @Override
    public BaseMapper<WxCheck, String> getMapper() {
        return wxCheckMapper;
    }

    private void initOrderItem(WxCheckItem wxCheckItem){

        Product product = productService.selectByPrimaryKey(wxCheckItem.getProductId());
        wxCheckItem.setSn(product.getSn());
        wxCheckItem.setName(product.getName());
        if (product.getSpec1()==null) {
            product.setSpec1("");
        }
        if (product.getSpec2()==null) {
            product.setSpec2("");
        }
        wxCheckItem.setSpec(product.getSpec1()+product.getSpec2());
        wxCheckItem.setUnit(product.getUnit());

        if (null == wxCheckItem.getBookQuantity()){
            wxCheckItem.setBookQuantity(BigDecimal.ZERO);
        }
        if (null == wxCheckItem.getPhysicalQuantity()){
            wxCheckItem.setPhysicalQuantity(BigDecimal.ZERO);
        }

        wxCheckItem.setPrice(product.getPrice());
        wxCheckItem.setCost(product.getCost());

    }

    @Transactional(rollbackFor = Exception.class)
    public int insertCheck(WxCheck wxCheck,String sn){
        Enterprise enterprise = enterpriseService.getCurrent();
        wxCheck.setCreateDate(new Date());
        wxCheck.setEnterpriseId(enterprise.getId());
        wxCheck.setOrderDate(DateUtils.truncate(new Date(),Calendar.DATE));
        wxCheck.setOrderStatus(0);
        wxCheck.setSn(sn);
        int affectCount = super.insertUseGeneratedKeys(wxCheck);
        if (affectCount > 0){
            List<WxCheckItem> itemList = wxCheck.getItemList();
            for (WxCheckItem wxCheckItem : itemList){
                initOrderItem(wxCheckItem);
                wxCheckItem.setCheckId(wxCheck.getId());
            }
            wxCheckItemService.insertUseGeneratedKeyList(itemList);
        }
        return affectCount;
    }


    public int saveAndConfirm(WxCheck wxCheck,String sn){
        this.insertCheck(wxCheck, sn);
        this.confirm(wxCheck.getId(), sysSequenceService.generate("check"));
        return 1;
    }

    @Transactional(rollbackFor = Exception.class)
    public int update(WxCheck wxCheck){
        //1、查询原订单信息
        WxCheck sourceCheck = wxCheckMapper.selectByPrimaryKey(wxCheck.getId());
        if (null == sourceCheck){
            throw new CustomException("盘点单不存在");
        }
        if (0 != sourceCheck.getOrderStatus()){
            throw new CustomException("盘点单已不可修改");
        }
        //2、计算订单金额，更新订单主表
        int affectCount = wxCheckMapper.updateByPrimaryKeySelective(wxCheck);
        if (affectCount > 0){
            /**
             * 3、原订单商品明细与编辑之后的商品明细对比
             * result = 0, insert
             * result = 1, update
             * result = 2, delete
             */
            WxCheckItem paramsItem = new WxCheckItem();
            paramsItem.setCheckId(sourceCheck.getId());
            List<WxCheckItem> sourceOrderItemList = wxCheckItemService.select(paramsItem);
            List<WxCheckItem> targetOrderItemList = wxCheck.getItemList();
            for (WxCheckItem targetOrderItem : targetOrderItemList){
                if (targetOrderItem.getId()==null) {
                    initOrderItem(targetOrderItem);
                    targetOrderItem.setCheckId(wxCheck.getId());
                    wxCheckItemService.insertUseGeneratedKeys(targetOrderItem);
                } else {
                    for (WxCheckItem sourceOrderItem : sourceOrderItemList){
                        if (targetOrderItem.getId().equals(sourceOrderItem.getId())){
                            sourceOrderItemList.remove(sourceOrderItem);
                            break;
                        }
                    }
                    wxCheckItemService.updateByPrimaryKeySelective(targetOrderItem);
                }
            }
            //4、删除未匹配中的数据
            if (null != sourceOrderItemList && sourceOrderItemList.size() > 0){
                for (WxCheckItem orderItem : sourceOrderItemList){
                    wxCheckItemService.deleteByPrimaryKey(orderItem.getId());
                }
            }
        }
        return affectCount;
    }

    @Transactional(rollbackFor = Exception.class)
    public int confirm(Long id,String sn) {
        WxCheck wxCheck = selectByPrimaryKey(id);
        if (null == wxCheck) {
            throw new CustomException("盘点单不存在");
        }
        if (wxCheck.getOrderStatus() != 0){
            throw new CustomException("盘点单已确认");
        }
        wxCheck.setOrderStatus(CheckStatusEnum.ALLOCATE_STATUS_CONFIRM.getId());
        int affectCount = wxCheckMapper.updateByPrimaryKeySelective(wxCheck);
        if (affectCount > 0){
            WxCheckItem param = new WxCheckItem();
            param.setCheckId(id);
            List<WxCheckItem> itemList = wxCheckItemService.select(param);
         /*   for (WxCheckItem wxCheckItem : itemList){
                //计算库存损益数量
                *//**
                 * 账面库存大于实物库存，盘亏，需出库
                 * 账面库存小于实物库存，盘赢，需入库
                 *//*
                BigDecimal actureQuantity = wxCheckItem.calcuteQuantity();
                if (actureQuantity.compareTo(BigDecimal.ZERO) != 0){
                    wxCheckItem.setPhysicalQuantity(actureQuantity);
                    targetList.add( wxCheckItem);
                }
            }*/
            wxCheck.setItemList(itemList);
            logger.info("生成出库单：[{}]", wxCheck);
            this.insertWarehouse(wxCheck, WarehouseTypeEnum.WAREHOUSE_TYPE_CHECK_OUT.getId(), sn, wxCheck.getSn());
        }
        return affectCount;
    }


    @Transactional(rollbackFor = Exception.class)
    public int cancel(Long id){
        int affectCount = 0;
        //1、判断单据是否存在
        WxCheck wxCheck = selectByPrimaryKey(id);
        if (null == wxCheck){
            throw new CustomException("盘点单不存在");
        }

        SysUser sysUser = sysUserService.getCurrent();
        Boolean isAdmin = sysUserService.isAdmin(sysUser);
        if (!isAdmin){
            if (!sysUser.getId().equals(wxCheck.getCreateBy())){
                throw new CustomException("当前人员非制单人员");
            }
        }

        if (wxCheck.getOrderStatus().equals(WxCheckOrderStatusEnum.ORDER_STATUS_CANCELED.getId())){
            throw new CustomException("单据已经作废,请勿重复作废");
        }else if (wxCheck.getOrderStatus().equals(WxCheckOrderStatusEnum.ORDER_STATUS_CONFIRM.getId())){

            //3、更新单据状态，并处理库存数据
            wxCheck.setOrderStatus(PurchaseOrderStatusEnum.ORDER_STATUS_CANCLE.getId());
            affectCount = super.updateByPrimaryKeySelective(wxCheck);
            if (affectCount > 0) {
                Warehouse params = new Warehouse();
                params.setOrderId(wxCheck.getId());
                List<Warehouse> warehouseList = warehouseService.select(params);
                if (null != warehouseList && warehouseList.size() > 0) {
                    for (Warehouse warehouse : warehouseList) {
                        //更新出库单从“已完成”到“已取消”
                        warehouse.setStatus(WarehouseStatusEnum.WAREHOUSE_STATUS_CANCEL.getId());
                        warehouseService.updateByPrimaryKeySelective(warehouse);
                        //回滚出库单的库存
                        WarehouseItem wareItem = new WarehouseItem();
                        wareItem.setWarehouseId(warehouse.getId());
                        List<WarehouseItem> warehouseItemList = warehouseItemService.select(wareItem);
                        for (WarehouseItem warehouseItem : warehouseItemList) {
                            warehouseStockService.afterCancelCompletion(warehouse.getWarehouseType(), warehouseItem);
                            warehouseStockService.preCancelHandle(warehouse.getWarehouseType(), warehouseItem);
                        }
                    }
                } else {
                    throw new CustomException("采购单尚未查找到对应的出入库单，请核对");
                }
            }
        }else{
            //未确认的判断单，直接作废，不需要操作库存
            wxCheck.setOrderStatus(WxCheckOrderStatusEnum.ORDER_STATUS_CANCELED.getId());
            affectCount = super.updateByPrimaryKeySelective(wxCheck);
        }
        return affectCount;
    }




    /**
     * 生成出入库
     * @param wxCheck
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertWarehouse(WxCheck wxCheck, Integer warehouseType, String sn, String orderSn){
        SysUser sysUser = sysUserService.getCurrent();
        Warehouse warehouse = new Warehouse();
        warehouse.setSn(sn);
        warehouse.setStatus(0);
        warehouse.setWarehouseType(warehouseType);
        //损益单据的数量和金额先暂时默认0
        warehouse.setSubPrice(BigDecimal.ZERO);
        warehouse.setSubQuantity(BigDecimal.ZERO);
        warehouse.setOrderId(wxCheck.getId());
        warehouse.setEnterpriseId(wxCheck.getEnterpriseId());
        warehouse.setShopId(wxCheck.getShopId());
        warehouse.setDeleted(false);
        warehouse.setOfficeId(wxCheck.getOfficeId());
        warehouse.setOperatorId(sysUser.getId());
        warehouse.setSPrint(0);
        warehouse.setOrderDate(DateUtils.truncate(new Date(), Calendar.DATE));
        warehouse.setOrderSn(orderSn);
        //明细表数据
        List<WarehouseItem> itemsList = new ArrayList<>();
        for (WxCheckItem wxCheckItem : wxCheck.getItemList()){
            Product product = productService.selectByPrimaryKey(wxCheckItem.getProductId());
            logger.info("生成出库单明细：[{}]----[{}]--[{}]--[{}]",wxCheckItem.getName(), wxCheckItem.getBookQuantity(), wxCheckItem.getPhysicalQuantity(), wxCheckItem.calcuteQuantity());
            WarehouseItem warehouseItem = new WarehouseItem();
            warehouseItem.setName(wxCheckItem.getName());
            warehouseItem.setPrice(wxCheckItem.getPrice());
            warehouseItem.setCost(wxCheckItem.getCost());
            warehouseItem.setQuantity(wxCheckItem.calcuteQuantity());
            warehouseItem.setSn(wxCheckItem.getSn());
            warehouseItem.setUnit(wxCheckItem.getUnit());
            warehouseItem.setSpec(wxCheckItem.getSpec());
            warehouseItem.setThumbnail(product.getThumbnail());
            warehouseItem.setProductId(wxCheckItem.getProductId());
            warehouseItem.setDiscount(BigDecimal.ZERO);
            //冗余存储
            warehouseItem.setShopId(warehouse.getShopId());
            warehouseItem.setEnterpriseId(warehouse.getEnterpriseId());
            warehouseItem.setTax(BigDecimal.ZERO);
            itemsList.add(warehouseItem);
        }
        warehouse.setItemList(itemsList);

        warehouse.setSubPrice(warehouse.calculateSubPrice());
        warehouse.setSubQuantity(warehouse.calculateSubQuantity());

        warehouseService.insertUseGeneratedKeys(warehouse);
        //自动确认
        warehouseService.confirm(warehouse.getId());

        warehouseService.audit(warehouse.getId());
    }
}

